/*
 ------------------------------------------------------------------------------
 Copyright (C) 2013 Eternal Games.

 This file is part of the EternalTech source code.

 The EternalTech source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The EternalTech source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the EternalTech source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


//
// sv_game.cpp - game module interface
//


#include "sv_local.h"
#include "../renderer/r_public.h"


static glqServer_t			glqServer;

glqSGame_t *				glqSGame = NULL;


/*
 ==============================================================================

 TODO

 ==============================================================================
*/


/*
 ==================
 SG_AddReliableCommand
 ==================
*/
static void SG_AddReliableCommand (int clientNum, const char *fmt, ...){

	char	command[MAX_STRING_LENGTH];
	va_list	argPtr;
	int		len;

	if (clientNum < 0 || clientNum >= sv_maxClients->integerValue)
		Com_Error(false, "SG_AddReliableCommand: clientNum out of range");

	va_start(argPtr, fmt);
	len = Str_VSPrintf(command, sizeof(command), fmt, argPtr);
	va_end(argPtr);

	if (len == -1)
		Com_Error(false, "SG_AddReliableCommand: command string overflow");

	SV_AddReliableCommand(&svs.clients[clientNum], "%s", command);
}

/*
 ==================
 SG_BroadcastReliableCommand
 ==================
*/
static void SG_BroadcastReliableCommand (const char *fmt, ...){

	char	command[MAX_STRING_LENGTH];
	va_list	argPtr;
	int		len;

	va_start(argPtr, fmt);
	len = Str_VSPrintf(command, sizeof(command), fmt, argPtr);
	va_end(argPtr);

	if (len == -1)
		Com_Error(false, "SG_BroadcastReliableCommand: command string overflow");

	SV_BroadcastReliableCommand("%s", command);
}

/*
 ==================
 SG_DropClient
 ==================
*/
static void SG_DropClient (int clientNum, const char *reason){

	if (clientNum < 0 || clientNum >= sv_maxClients->integerValue)
		Com_Error(false, "SG_DropClient: clientNum out of range");

	SV_DropClient(&svs.clients[clientNum], reason);
}


/*
 ==============================================================================

 FRAMEWORK

 ==============================================================================
*/


/*
 ==================
 SG_SetupFramework
 ==================
*/
void SG_SetupFramework (){

	// Common functions
	glqServer.glqCommon.Printf							= Com_Printf;
	glqServer.glqCommon.DPrintf							= Com_DPrintf;
	glqServer.glqCommon.Error							= Com_Error;
	glqServer.glqCommon.LaunchEditor					= Com_LaunchEditor;
	glqServer.glqCommon.CloseEditor						= Com_CloseEditor;
	glqServer.glqCommon.IsEditorActive					= Com_IsEditorActive;

	// Memory functions
	glqServer.glqMemory.Alloc							= Mem_Alloc;
	glqServer.glqMemory.Alloc16							= Mem_Alloc16;
	glqServer.glqMemory.ClearedAlloc					= Mem_ClearedAlloc;
	glqServer.glqMemory.ClearedAlloc16					= Mem_ClearedAlloc16;
	glqServer.glqMemory.Free							= Mem_Free;
	glqServer.glqMemory.FreeAll							= Mem_FreeAll;
	glqServer.glqMemory.Size							= Mem_Size;
	glqServer.glqMemory.Fill							= Mem_Fill;
	glqServer.glqMemory.Copy							= Mem_Copy;
	glqServer.glqMemory.Compare							= Mem_Compare;
	glqServer.glqMemory.DupString						= Mem_DupString;
	glqServer.glqMemory.DupData							= Mem_DupData;

	// File system functions
	glqServer.glqFileSystem.Read						= FS_Read;
	glqServer.glqFileSystem.Write						= FS_Write;
	glqServer.glqFileSystem.Printf						= FS_Printf;
	glqServer.glqFileSystem.OpenFile					= FS_OpenFile;
	glqServer.glqFileSystem.CloseFile					= FS_CloseFile;
	glqServer.glqFileSystem.RemoveFile					= FS_RemoveFile;
	glqServer.glqFileSystem.FileExists					= FS_FileExists;
	glqServer.glqFileSystem.FindFile					= FS_FindFile;
	glqServer.glqFileSystem.ReadFile					= FS_ReadFile;
	glqServer.glqFileSystem.FreeFile					= FS_FreeFile;
	glqServer.glqFileSystem.WriteFile					= FS_WriteFile;
	glqServer.glqFileSystem.ExtractLibrary				= FS_ExtractLibrary;
	glqServer.glqFileSystem.ListFiles					= FS_ListFiles;
	glqServer.glqFileSystem.ListFilteredFiles			= FS_ListFilteredFiles;
	glqServer.glqFileSystem.FreeFileList				= FS_FreeFileList;

	// Command system functions
	glqServer.glqCmdSystem.AddCommand					= Cmd_AddCommand;
	glqServer.glqCmdSystem.RemoveCommand				= Cmd_RemoveCommand;
	glqServer.glqCmdSystem.ArgCompletion_PathExtension	= Cmd_ArgCompletion_PathExtension;
	glqServer.glqCmdSystem.ArgCompletion_Definition		= Cmd_ArgCompletion_Definition;
	glqServer.glqCmdSystem.ArgCompletion_ConfigName		= Cmd_ArgCompletion_ConfigName;
	glqServer.glqCmdSystem.ArgCompletion_DemoName		= Cmd_ArgCompletion_DemoName;
	glqServer.glqCmdSystem.ArgCompletion_MapName		= Cmd_ArgCompletion_MapName;
	glqServer.glqCmdSystem.ArgCompletion_ModelName		= Cmd_ArgCompletion_ModelName;
	glqServer.glqCmdSystem.ArgCompletion_ImageName		= Cmd_ArgCompletion_ImageName;
	glqServer.glqCmdSystem.ArgCompletion_SkinName		= Cmd_ArgCompletion_SkinName;
	glqServer.glqCmdSystem.ArgCompletion_MaterialName	= Cmd_ArgCompletion_MaterialName;
	glqServer.glqCmdSystem.Argc							= Cmd_Argc;
	glqServer.glqCmdSystem.Argv							= Cmd_Argv;
	glqServer.glqCmdSystem.Args							= Cmd_Args;
	glqServer.glqCmdSystem.TokenizeString				= Cmd_TokenizeString;
	glqServer.glqCmdSystem.AppendText					= Cmd_AppendText;
	glqServer.glqCmdSystem.InsertText					= Cmd_InsertText;
	glqServer.glqCmdSystem.ExecuteText					= Cmd_ExecuteText;

	// CVar system functions
	glqServer.glqCVarSystem.Register					= CVar_Register;
	glqServer.glqCVarSystem.SetBool						= CVar_SetBool;
	glqServer.glqCVarSystem.SetInteger					= CVar_SetInteger;
	glqServer.glqCVarSystem.SetFloat					= CVar_SetFloat;
	glqServer.glqCVarSystem.SetString					= CVar_SetString;
	glqServer.glqCVarSystem.UpdateLatched				= CVar_UpdateLatched;
	glqServer.glqCVarSystem.FindVariable				= CVar_FindVariable;
	glqServer.glqCVarSystem.GetVariableBool				= CVar_GetVariableBool;
	glqServer.glqCVarSystem.GetVariableInteger			= CVar_GetVariableInteger;
	glqServer.glqCVarSystem.GetVariableFloat			= CVar_GetVariableFloat;
	glqServer.glqCVarSystem.GetVariableString			= CVar_GetVariableString;
	glqServer.glqCVarSystem.SetVariableBool				= CVar_SetVariableBool;
	glqServer.glqCVarSystem.SetVariableInteger			= CVar_SetVariableInteger;
	glqServer.glqCVarSystem.SetVariableFloat			= CVar_SetVariableFloat;
	glqServer.glqCVarSystem.SetVariableString			= CVar_SetVariableString;
	glqServer.glqCVarSystem.AllowCheats					= CVar_AllowCheats;
	glqServer.glqCVarSystem.GetModifiedFlags			= CVar_GetModifiedFlags;
	glqServer.glqCVarSystem.SetModifiedFlags			= CVar_SetModifiedFlags;
	glqServer.glqCVarSystem.ClearModifiedFlags			= CVar_ClearModifiedFlags;
	glqServer.glqCVarSystem.InfoString					= CVar_InfoString;

	// Message system functions
	glqServer.glqMsgSystem.Init							= MSG_Init;
	glqServer.glqMsgSystem.GetWriteState				= MSG_GetWriteState;
	glqServer.glqMsgSystem.SetWriteState				= MSG_SetWriteState;
	glqServer.glqMsgSystem.ClearWriteState				= MSG_ClearWriteState;
	glqServer.glqMsgSystem.RemainingWriteBits			= MSG_RemainingWriteBits;
	glqServer.glqMsgSystem.RemainingWriteBytes			= MSG_RemainingWriteBytes;
	glqServer.glqMsgSystem.WriteAlign					= MSG_WriteAlign;
	glqServer.glqMsgSystem.WriteBits					= MSG_WriteBits;
	glqServer.glqMsgSystem.WriteBool					= MSG_WriteBool;
	glqServer.glqMsgSystem.WriteChar					= MSG_WriteChar;
	glqServer.glqMsgSystem.WriteByte					= MSG_WriteByte;
	glqServer.glqMsgSystem.WriteShort					= MSG_WriteShort;
	glqServer.glqMsgSystem.WriteWord					= MSG_WriteWord;
	glqServer.glqMsgSystem.WriteLong					= MSG_WriteLong;
	glqServer.glqMsgSystem.WriteHalf					= MSG_WriteHalf;
	glqServer.glqMsgSystem.WriteFloat					= MSG_WriteFloat;
	glqServer.glqMsgSystem.WriteAngle					= MSG_WriteAngle;
	glqServer.glqMsgSystem.WriteAngle8					= MSG_WriteAngle8;
	glqServer.glqMsgSystem.WriteAngle16					= MSG_WriteAngle16;
	glqServer.glqMsgSystem.WriteAngles					= MSG_WriteAngles; 
	glqServer.glqMsgSystem.WriteAngles8					= MSG_WriteAngles8;
	glqServer.glqMsgSystem.WriteAngles16				= MSG_WriteAngles16;
	glqServer.glqMsgSystem.WriteVec2					= MSG_WriteVec2;
	glqServer.glqMsgSystem.WriteVec3					= MSG_WriteVec3;
	glqServer.glqMsgSystem.WriteVec4					= MSG_WriteVec4;
	glqServer.glqMsgSystem.WriteVec5					= MSG_WriteVec5;
	glqServer.glqMsgSystem.WriteNormal					= MSG_WriteNormal;
	glqServer.glqMsgSystem.WriteString					= MSG_WriteString;
	glqServer.glqMsgSystem.WriteData					= MSG_WriteData;
	glqServer.glqMsgSystem.WriteDeltaBits				= MSG_WriteDeltaBits;
	glqServer.glqMsgSystem.WriteDeltaChar				= MSG_WriteDeltaChar;
	glqServer.glqMsgSystem.WriteDeltaByte				= MSG_WriteDeltaByte;
	glqServer.glqMsgSystem.WriteDeltaShort				= MSG_WriteDeltaShort;
	glqServer.glqMsgSystem.WriteDeltaWord				= MSG_WriteDeltaWord;
	glqServer.glqMsgSystem.WriteDeltaLong				= MSG_WriteDeltaLong;
	glqServer.glqMsgSystem.WriteDeltaHalf				= MSG_WriteDeltaHalf;
	glqServer.glqMsgSystem.WriteDeltaFloat				= MSG_WriteDeltaFloat;
	glqServer.glqMsgSystem.WriteDeltaAngle				= MSG_WriteDeltaAngle;
	glqServer.glqMsgSystem.WriteDeltaAngle8				= MSG_WriteDeltaAngle8;
	glqServer.glqMsgSystem.WriteDeltaAngle16			= MSG_WriteDeltaAngle16;
	glqServer.glqMsgSystem.WriteDeltaAngles				= MSG_WriteDeltaAngles;
	glqServer.glqMsgSystem.WriteDeltaAngles8			= MSG_WriteDeltaAngles8;
	glqServer.glqMsgSystem.WriteDeltaAngles16			= MSG_WriteDeltaAngles16;
	glqServer.glqMsgSystem.WriteDeltaVec2				= MSG_WriteDeltaVec2;
	glqServer.glqMsgSystem.WriteDeltaVec3				= MSG_WriteDeltaVec3;
	glqServer.glqMsgSystem.WriteDeltaVec4				= MSG_WriteDeltaVec4;
	glqServer.glqMsgSystem.WriteDeltaVec5				= MSG_WriteDeltaVec5;
	glqServer.glqMsgSystem.WriteDeltaNormal				= MSG_WriteDeltaNormal;
	glqServer.glqMsgSystem.GetReadState					= MSG_GetReadState;
	glqServer.glqMsgSystem.SetReadState					= MSG_SetReadState;
	glqServer.glqMsgSystem.ClearReadState				= MSG_ClearReadState;
	glqServer.glqMsgSystem.RemainingReadBits			= MSG_RemainingReadBits;
	glqServer.glqMsgSystem.RemainingReadBytes			= MSG_RemainingReadBytes;
	glqServer.glqMsgSystem.ReadAlign					= MSG_ReadAlign;
	glqServer.glqMsgSystem.ReadBits						= MSG_ReadBits;
	glqServer.glqMsgSystem.ReadBool						= MSG_ReadBool;
	glqServer.glqMsgSystem.ReadChar						= MSG_ReadChar;
	glqServer.glqMsgSystem.ReadByte						= MSG_ReadByte;
	glqServer.glqMsgSystem.ReadShort					= MSG_ReadShort;
	glqServer.glqMsgSystem.ReadWord						= MSG_ReadWord;
	glqServer.glqMsgSystem.ReadLong						= MSG_ReadLong;
	glqServer.glqMsgSystem.ReadHalf						= MSG_ReadHalf;
	glqServer.glqMsgSystem.ReadFloat					= MSG_ReadFloat;
	glqServer.glqMsgSystem.ReadAngle					= MSG_ReadAngle;
	glqServer.glqMsgSystem.ReadAngle8					= MSG_ReadAngle8;
	glqServer.glqMsgSystem.ReadAngle16					= MSG_ReadAngle16;
	glqServer.glqMsgSystem.ReadAngles					= MSG_ReadAngles;
	glqServer.glqMsgSystem.ReadAngles8					= MSG_ReadAngles8;
	glqServer.glqMsgSystem.ReadAngles16					= MSG_ReadAngles16;
	glqServer.glqMsgSystem.ReadVec2						= MSG_ReadVec2;
	glqServer.glqMsgSystem.ReadVec3						= MSG_ReadVec3;
	glqServer.glqMsgSystem.ReadVec4						= MSG_ReadVec4;
	glqServer.glqMsgSystem.ReadVec5						= MSG_ReadVec5;
	glqServer.glqMsgSystem.ReadNormal					= MSG_ReadNormal;
	glqServer.glqMsgSystem.ReadString					= MSG_ReadString;
	glqServer.glqMsgSystem.ReadData						= MSG_ReadData;
	glqServer.glqMsgSystem.ReadDeltaBits				= MSG_ReadDeltaBits;
	glqServer.glqMsgSystem.ReadDeltaChar				= MSG_ReadDeltaChar;
	glqServer.glqMsgSystem.ReadDeltaByte				= MSG_ReadDeltaByte;
	glqServer.glqMsgSystem.ReadDeltaShort				= MSG_ReadDeltaShort;
	glqServer.glqMsgSystem.ReadDeltaWord				= MSG_ReadDeltaWord;
	glqServer.glqMsgSystem.ReadDeltaLong				= MSG_ReadDeltaLong;
	glqServer.glqMsgSystem.ReadDeltaHalf				= MSG_ReadDeltaHalf;
	glqServer.glqMsgSystem.ReadDeltaFloat				= MSG_ReadDeltaFloat;
	glqServer.glqMsgSystem.ReadDeltaAngle				= MSG_ReadDeltaAngle;
	glqServer.glqMsgSystem.ReadDeltaAngle8				= MSG_ReadDeltaAngle8;
	glqServer.glqMsgSystem.ReadDeltaAngle16				= MSG_ReadDeltaAngle16;
	glqServer.glqMsgSystem.ReadDeltaAngles				= MSG_ReadDeltaAngles;
	glqServer.glqMsgSystem.ReadDeltaAngles8				= MSG_ReadDeltaAngles8;
	glqServer.glqMsgSystem.ReadDeltaAngles16			= MSG_ReadDeltaAngles16;
	glqServer.glqMsgSystem.ReadDeltaVec2				= MSG_ReadDeltaVec2;
	glqServer.glqMsgSystem.ReadDeltaVec3				= MSG_ReadDeltaVec3;
	glqServer.glqMsgSystem.ReadDeltaVec4				= MSG_ReadDeltaVec4;
	glqServer.glqMsgSystem.ReadDeltaVec5				= MSG_ReadDeltaVec5;
	glqServer.glqMsgSystem.ReadDeltaNormal				= MSG_ReadDeltaNormal;

	// Definition manager functions
	glqServer.glqDefManager.RegisterType				= Def_RegisterType;
	glqServer.glqDefManager.LoadDefs					= Def_LoadDefs;
	glqServer.glqDefManager.PurgeDefs					= Def_PurgeDefs;
	glqServer.glqDefManager.EnumDefs					= Def_EnumDefs;
	glqServer.glqDefManager.GetNumDefs					= Def_GetNumDefs;
	glqServer.glqDefManager.GetDefByIndex				= Def_GetDefByIndex;
	glqServer.glqDefManager.FindDef						= Def_FindDef;

	// Parser functions
	glqServer.glqParser.ReadToken						= PS_ReadToken;
	glqServer.glqParser.UnreadToken						= PS_UnreadToken;
	glqServer.glqParser.ReadBool						= PS_ReadBool;
	glqServer.glqParser.ReadInteger						= PS_ReadInteger;
	glqServer.glqParser.ReadFloat						= PS_ReadFloat;
	glqServer.glqParser.ReadMatrix1D					= PS_ReadMatrix1D;
	glqServer.glqParser.ReadMatrix2D					= PS_ReadMatrix2D;
	glqServer.glqParser.ReadMatrix3D					= PS_ReadMatrix3D;
	glqServer.glqParser.ExpectTokenString				= PS_ExpectTokenString;
	glqServer.glqParser.ExpectTokenType					= PS_ExpectTokenType;
	glqServer.glqParser.CheckTokenString				= PS_CheckTokenString;
	glqServer.glqParser.CheckTokenType					= PS_CheckTokenType;
	glqServer.glqParser.PeekTokenString					= PS_PeekTokenString;
	glqServer.glqParser.PeekTokenType					= PS_PeekTokenType;
	glqServer.glqParser.TokenAvailable					= PS_TokenAvailable;
	glqServer.glqParser.SkipUntilString					= PS_SkipUntilString;
	glqServer.glqParser.SkipRestOfLine					= PS_SkipRestOfLine;
	glqServer.glqParser.SkipBracedSection				= PS_SkipBracedSection;
	glqServer.glqParser.ScriptWarning					= PS_ScriptWarning;
	glqServer.glqParser.ScriptError						= PS_ScriptError;
	glqServer.glqParser.ResetScript						= PS_ResetScript;
	glqServer.glqParser.EndOfScript						= PS_EndOfScript;
	glqServer.glqParser.SetScriptFlags					= PS_SetScriptFlags;
	glqServer.glqParser.SetPunctuationsTable			= PS_SetPunctuationsTable;
	glqServer.glqParser.LoadScriptFile					= PS_LoadScriptFile;
	glqServer.glqParser.LoadScriptMemory				= PS_LoadScriptMemory;
	glqServer.glqParser.FreeScript						= PS_FreeScript;

	// System functions
	glqServer.glqSystem.ListFiles						= Sys_ListFiles;
	glqServer.glqSystem.ListFilteredFiles				= Sys_ListFilteredFiles;
	glqServer.glqSystem.FreeFileList					= Sys_FreeFileList;
	glqServer.glqSystem.CreateDirectory					= Sys_CreateDirectory;
	glqServer.glqSystem.RemoveDirectory					= Sys_RemoveDirectory;
	glqServer.glqSystem.CurrentDirectory				= Sys_CurrentDirectory;
	glqServer.glqSystem.DefaultBaseDirectory			= Sys_DefaultBaseDirectory;
	glqServer.glqSystem.DefaultSaveDirectory			= Sys_DefaultSaveDirectory;
	glqServer.glqSystem.DiskFreeSpace					= Sys_DiskFreeSpace;
	glqServer.glqSystem.LoadLibrary						= Sys_LoadLibrary;
	glqServer.glqSystem.FreeLibrary						= Sys_FreeLibrary;
	glqServer.glqSystem.GetProcAddress					= Sys_GetProcAddress;
	glqServer.glqSystem.GetProcessorId					= Sys_GetProcessorId;
	glqServer.glqSystem.GetProcessorCount				= Sys_GetProcessorCount;
	glqServer.glqSystem.GetProcessorString				= Sys_GetProcessorString;
	glqServer.glqSystem.DebugBreak						= Sys_DebugBreak;
	glqServer.glqSystem.Sleep							= Sys_Sleep;
	glqServer.glqSystem.Milliseconds					= Sys_Milliseconds;
	glqServer.glqSystem.ClockTicks						= Sys_ClockTicks;
	glqServer.glqSystem.ClockTicksPerSecond				= Sys_ClockTicksPerSecond;
	glqServer.glqSystem.GetInstanceHandle				= Sys_GetInstanceHandle;
	glqServer.glqSystem.GetIconHandle					= Sys_GetIconHandle;
	glqServer.glqSystem.GetClipboardText				= Sys_GetClipboardText;
	glqServer.glqSystem.SetClipboardText				= Sys_SetClipboardText;
	glqServer.glqSystem.StartProcess					= Sys_StartProcess;
	glqServer.glqSystem.OpenURL							= Sys_OpenURL;

	// Table functions
	glqServer.glqTable.FindTable						= LUT_FindTable;
	glqServer.glqTable.LookupTable						= LUT_LookupTable;

	// Collision functions
	glqServer.glqCollision.LoadMap						= CM_LoadMap;
	glqServer.glqCollision.RegisterModel				= CM_RegisterModel;
	glqServer.glqCollision.GetModelBounds				= CM_GetModelBounds;
	glqServer.glqCollision.SetupBoxModel				= CM_SetupBoxModel;
	glqServer.glqCollision.EntityString					= CM_EntityString;
	glqServer.glqCollision.Trace						= CM_Trace;
	glqServer.glqCollision.LeafPVS						= CM_LeafPVS;
	glqServer.glqCollision.PointInLeaf					= CM_PointInLeaf;

	// Renderer functions
	glqServer.glqRenderer.DebugAxis						= R_DebugAxis;
	glqServer.glqRenderer.DebugLine						= R_DebugLine;
	glqServer.glqRenderer.DebugArrow					= R_DebugArrow;
	glqServer.glqRenderer.DebugBounds					= R_DebugBounds;
	glqServer.glqRenderer.DebugSphere					= R_DebugSphere;
	glqServer.glqRenderer.DebugBox						= R_DebugBox;
	glqServer.glqRenderer.DebugCone						= R_DebugCone;
	glqServer.glqRenderer.DebugCircle					= R_DebugCircle;
	glqServer.glqRenderer.DebugFrustum					= R_DebugFrustum;
	glqServer.glqRenderer.DebugPolygon					= R_DebugPolygon;
	glqServer.glqRenderer.DebugText						= R_DebugText;

	// Server functions
	glqServer.AddReliableCommand						= SG_AddReliableCommand;
	glqServer.BroadcastReliableCommand					= SG_BroadcastReliableCommand;
	glqServer.DropClient								= SG_DropClient;
}


/*
 ==============================================================================

 INITIALIZATION & SHUTDOWN

 ==============================================================================
*/


/*
 ==================
 SG_Init
 ==================
*/
void SG_Init (){

	char		path[MAX_PATH_LENGTH];
	GETSGAMEAPI	GetSGameAPI;

	// Set up the framework
	SG_SetupFramework();

	// Extract the game module from a pack file
	if (!FS_ExtractLibrary("SGame", path))
		Com_Error(true, "Could not extract server game module");

	// Load the game module
	Com_Printf("Loading server game module\n");

	svs.gameLibHandle = Sys_LoadLibrary(path);
	if (!svs.gameLibHandle)
		Com_Error(true, "Could not load server game module");

	// Get the game API
	GetSGameAPI = (GETSGAMEAPI)Sys_GetProcAddress(svs.gameLibHandle, "GetSGameAPI");
	if (!GetSGameAPI)
		Com_Error(true, "Could not get server game interface");

	glqSGame = GetSGameAPI(&glqServer);

	if (glqSGame->apiVersion != SGAME_API_VERSION)
		Com_Error(true, "Server game interface version is %i, expected version %i", glqSGame->apiVersion, SGAME_API_VERSION);

	// Initialize the game
	glqSGame->Init(sv_map->value, svs.time);
}

/*
 ==================
 SG_Shutdown
 ==================
*/
void SG_Shutdown (){

	if (!svs.gameLibHandle)
		return;

	// Shutdown the game
	if (glqSGame){
		glqSGame->Shutdown();
		glqSGame = NULL;
	}

	// Free all game allocations
	Mem_FreeAll(TAG_SERVER, true);

	// Free the game module
	Com_Printf("Unloading server game module\n");

	Sys_FreeLibrary(svs.gameLibHandle);
	svs.gameLibHandle = 0;
}